package com.dl.test.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

/**
 * @author DL
 * @create 2025-03-25 14:47
 */
@RestController
@RequestMapping("/async")
public class AsyncController {

    @GetMapping("/zip")
    public Mono<String> zip() {
        // 定义任务 A：模拟从数据库查询用户信息
        Mono<String> taskA = Mono.fromCallable(() -> {
            simulateDelay(2000); // 模拟耗时 2 秒
            return "User Info";
        }).subscribeOn(Schedulers.boundedElastic());

        // 定义任务 B：模拟从远程服务获取订单信息
        Mono<String> taskB = Mono.fromCallable(() -> {
            simulateDelay(3000); // 模拟耗时 3 秒
            return "Order Info";
        }).subscribeOn(Schedulers.boundedElastic());

        // 定义任务 C：模拟从缓存中读取商品信息
        Mono<String> taskC = Mono.fromCallable(() -> {
            simulateDelay(1000); // 模拟耗时 1 秒
            return "Product Info";
        }).subscribeOn(Schedulers.boundedElastic());

        // 异步编排：等待所有任务完成并合并结果
        return Mono.zip(taskA, taskB, taskC)
                .map(tuple -> String.format("Task Results: %s | %s | %s",
                        tuple.getT1(), tuple.getT2(), tuple.getT3()));
    }

    @GetMapping("/first")
    public Mono<String> asyncTasks() {
        // 定义任务 A：模拟从数据库查询用户信息
        Mono<String> taskA = Mono.fromCallable(() -> {
            simulateDelay(2000); // 模拟耗时 2 秒
            return "User Info";
        }).subscribeOn(Schedulers.boundedElastic());

        // 定义任务 B：模拟从远程服务获取订单信息
        Mono<String> taskB = Mono.fromCallable(() -> {
            simulateDelay(3000); // 模拟耗时 3 秒
            return "Order Info";
        }).subscribeOn(Schedulers.boundedElastic());

        // 定义任务 C：模拟从缓存中读取商品信息
        Mono<String> taskC = Mono.fromCallable(() -> {
            simulateDelay(1000); // 模拟耗时 1 秒
            return "Product Info";
        }).subscribeOn(Schedulers.boundedElastic());

        // 等待最快的
        return Mono.firstWithValue(taskA, taskB, taskC);
    }

    // 模拟延迟方法
    private void simulateDelay(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}
